﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Xml;
using System.Linq;
using LitJson;

namespace SurrealTodoAdapter
{
    internal class SurrealTodoAdapter
    {
        private string _baseUrl = "http://qugaoding.com.cat211.redphp.cn/ajax.php";
        private Random _random = new Random((int)DateTime.Now.Ticks);
        private readonly WebClient _webClient;

        public SurrealTodoAdapter()
        {
            _webClient = new WebClient();
        }

        public SurrealTodoAdapter(string baseUrl)
            : this()
        {
            _baseUrl = baseUrl;
        }

        public TaskList AddNewList(string pageId)
        {
            string paramsString = "?action=newList&page_id=" + pageId + "&rand=" + _random.NextDouble();
            string taskXml = this.Get(_baseUrl + paramsString).Replace("onclick=myCallback(this)", string.Empty); ;
            var xmlDocument = new XmlDocument();
            xmlDocument.LoadXml(taskXml);
            var taskList = BuildTaskListFromXml(xmlDocument.DocumentElement);
            return taskList;
        }

        public Task AddNewTaskInList(int listId, string taskContent, DateTime taskTime)
        {
            string paramsString = "?action=newItem&list_id=" + listId + "&show_item_date=0&rand=" + _random.NextDouble();
            string taskXml = this.Get(_baseUrl + paramsString).Replace("onclick=myCallback(this)", string.Empty);
            var xmlDocument = new XmlDocument();
            xmlDocument.LoadXml(taskXml);

            Task task = BuildTaskFromXml(xmlDocument.DocumentElement);
            EditTask(task.id, taskContent);
            task.text = taskContent;

            return task;
        }

        public void EditTask(string taskId, string taskContent)
        {
            string postData = "action=editItem&id=" + taskId
                + "&text=" + taskContent
                + "&rand=" + _random.NextDouble();

            Post(_baseUrl, postData);
        }

        public void ChangeList(string taskId, int listId)
        {
            string paramsString = "?action=changeList&id=" + taskId + "&list_id=" + listId + "&rand=" + _random.NextDouble();
            Get(_baseUrl + paramsString);
        }


        public User CreateUser(string userName)
        {
            string paramsString = "?action=newTab&id=0&rand=" + _random.NextDouble();
            string tabJson = Get(_baseUrl + paramsString);
            User user = JsonMapper.ToObject<List<User>>(tabJson).First();

            EditUser(user.tab_id, userName);
            user.name = userName;
            return user;
        }

        public void EditUser(string userId, string userName)
        {
            string paramsString = "?action=editTab&id=" + userId
                + "&name=" + userName
                + "&rand=" + _random.NextDouble();
            Get(_baseUrl + paramsString);
        }

        public List<User> GetUsers()
        {
            string paramsString = "?_=" + _random.NextDouble() + "&action=tabs";
            string tabJson = Get(_baseUrl + paramsString);
            List<User> userCollection = JsonMapper.ToObject<List<User>>(tabJson);
            return userCollection;
        }

        public List<TaskPage> GetPages(string userId)
        {
            string paramsString = "?action=pages&tab_id=" + userId + "&rand=" + _random.NextDouble();
            string pagesJson = Get(_baseUrl + paramsString);

            List<TaskPage> taskPageList = JsonMapper.ToObject<List<TaskPage>>(pagesJson);
            return taskPageList;
        }

        public void EditList(int listId, string listName)
        {
            string paramsString = "?action=editList&id=" + listId
                + "&name=" + listName +
                "&rand=" + _random.NextDouble();
            Get(_baseUrl + paramsString);


        }


        public List<TaskList> GetTaskLists(string pageId)
        {
            string paramsString = "?action=lists&page_id=" + pageId + "&rand=" + _random.NextDouble();
            string taskListXml = Get(_baseUrl + paramsString);

            var taskList = new List<TaskList>();

            taskListXml = taskListXml.Substring(0, taskListXml.IndexOf("<script")).Replace("onclick=myCallback(this)", string.Empty);
            var xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(taskListXml);

            var listNodes = xmlDoc.SelectNodes("//li[@class='sortableList']");
            if (listNodes != null)
                foreach (XmlNode listNode in listNodes)
                {
                    taskList.Add(BuildTaskListFromXml(listNode));
                }

            return taskList;
        }

        public void DeleteUser(string tabId)
        {
            string paramsString = "?action=markDeleteTab&id=" + tabId + "&rand=" + _random.NextDouble();
            Get(_baseUrl + paramsString);
        }

        public void DeleteTask(string taskId)
        {
            string paramsString = "?action=markDeleteItem&id=" + taskId + "&rand=" + _random.NextDouble();
            Get(_baseUrl + paramsString);
        }

        public void DeletePage(int pageId)
        {
            string paramsString = "?action=markDeletePage&page_id=" + pageId + "&rand=" + _random.NextDouble();
            Get(_baseUrl + paramsString);
        }

        public void DeleteList(string listId)
        {
            string paramsString = "?action=markDeleteList&id=" + listId + "&rand=" + _random.NextDouble();
            Get(_baseUrl + paramsString);
        }

        public void AddTiming(string taskId, string userName, DateTime timing)
        {
            string paramsString = "?action=newTiming&id=" + taskId + "&username=" + userName + "&date=" + timing.ToString("yyyy-MM-dd hh:mm:ss");
            Get(_baseUrl + paramsString);
        }

        public List<TimingTask> GetTimingTasks()
        {
            const string paramsString = "?action=timings";
            string jsonTasks = Get(_baseUrl + paramsString);
            return JsonMapper.ToObject<List<TimingTask>>(jsonTasks);
        }


        private static Task BuildTaskFromXml(XmlNode item)
        {
            var task = new Task();
            //数据为id=item-45,所以从第5位开始取
            task.id = item.Attributes["id"].InnerText.Substring(5);
            task.text = item.SelectSingleNode("div[@class='text']").InnerText;
            task.date_created = Convert.ToDateTime(item.SelectSingleNode("div[@class='dateCreated']").InnerText);
            return task;
        }

        private static TaskList BuildTaskListFromXml(XmlNode listNode)
        {
            var taskList = new TaskList();

            //数据为id=List-45,所以从第5位开始取
            taskList.Id = Convert.ToInt32(listNode.Attributes["id"].InnerText.Substring(5));
            taskList.Name = listNode.SelectSingleNode("//div[@class='listName']").InnerText;
            taskList.DateCreated = Convert.ToDateTime(listNode.SelectSingleNode("//div[@class='listCreated']").InnerText);

            var itemNodes = listNode.SelectNodes("//li[@class='item']");

            if (itemNodes != null)
                foreach (XmlNode item in itemNodes)
                {
                    Task task = BuildTaskFromXml(item);
                    taskList.Tasks.Add(task);
                }
            return taskList;
        }


        private bool Post(string url, string postData)
        {
            var wc = new WebClient();
            byte[] sendData = Encoding.UTF8.GetBytes(postData);
            wc.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
            wc.Headers.Add("ContentLength", sendData.Length.ToString());

            byte[] recData = wc.UploadData(url, "POST", sendData);

            string result = Encoding.UTF8.GetString(recData);

            return result == "1";
        }

        private string Get(string url)
        {
            var webClient = new WebClient();
            webClient.Encoding = Encoding.UTF8;
            return webClient.DownloadString(url);
        }
    }
}